package com.sjs.boot.dynamic.core.run;

import cn.hutool.core.util.StrUtil;
import com.sjs.boot.dynamic.core.config.method.MethodConfig;
import com.sjs.boot.dynamic.core.config.method.parameter.ParameterInfo;
import com.sjs.boot.dynamic.protocol.Const;
import com.sjs.boot.dynamic.protocol.RetCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * @author uto_dev_008
 * @desc
 * @since 2021/11/9 18:38
 */
public class MethodContext {
    private static final Logger LOG = LoggerFactory.getLogger(MethodContext.class);

    private HttpServletRequest request = null;
    private HttpServletResponse response = null;
    private MethodConfig config = null;
    private Map<String, Object> parameters = null;
    private String result = null; //如果设置了字符串结果，则不再使用results
    private Map<String, Object> results = new HashMap<>();
    private int resultCode = -1; //如果设置为OK，默认的info success设置不进去


    public MethodContext(MethodConfig config, HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
        this.config = config;
        this.setResult(RetCode.OK.getCode(), Const.SUCCESS); //默认ok
    }

    /**
     * 用于复制会话，在接口需要并发多线程执行，每个接口参数不同时，使用复制
     *
     * @param parent
     * @param parameters
     * @param results
     */
    public MethodContext(MethodContext parent, Map<String, Object> parameters, Map<String, Object> results) {
        this.request = parent.request;
        this.response = parent.response;
        this.config = parent.config;
        this.parameters = parameters; //请求参数
        this.results = results; //响应参数
        this.resultCode = parent.resultCode;
    }

    public MethodContext(MethodContext parent, Map<String, Object> results) {
        this(parent, parent.parameters, results);
    }

    public HttpServletRequest getRequest() {
        return request;
    }


    public MethodConfig getMethodConfig() {
        return config;
    }

    public void addParameters(Map<String, Object> parameters) {
        if (parameters == null) {
            return;
        }
        this.parameters.putAll(parameters);
    }

    public void setParameters(Map<String, Object> parameters) {
        this.parameters = parameters;
    }

    public void setParameter(String key, Object val) {
        parameters.put(key, val);
    }

    public Map<String, Object> getParameters() {
        return parameters;
    }

    /**
     * 通过参数名称获取参数的值，
     *
     * @param name
     * @return
     */
    public Object getParameter(String name) {
        return parameters.get(name);
    }

    /**
     * 通过参数名称获取参数的值，
     * 通过ParameterInfo的getValue获得，考虑了默认值、映射等
     *
     * @param name
     * @return
     */
    public Object getContextParameter(String name) {
        ParameterInfo pi = config.getRequestConfig().getParameter(name);
        return pi != null ? pi.getValue(this) : null;
    }

    /**
     * 设置返回码与返回信息，可能会被设置多次
     *
     * @param retCode
     * @param reason
     * @param coverIt 覆盖原有的reason
     */
    public int setResult(int retCode, String reason, boolean coverIt) {
        if (coverIt || resultCode != retCode) {
            if (StrUtil.isEmpty(reason)) {
                reason = config.getResponseConfig().getReason(retCode);
                if (StrUtil.isEmpty(reason)) {
                    reason = RetCode.getMsg(retCode);
                }
                this.results.put(config.getReasonName(), reason == null ? "Unknown" : reason);
            } else {
                this.results.put(config.getReasonName(), reason);
            }
        }
        this.resultCode = retCode;
        this.results.put(config.getResultCodeName(), this.resultCode);
        return retCode;
    }

    public int setResult(int retCode, String reason) {
        return setResult(retCode, reason, false);
    }

    /**
     * 设置返回码，错误原因从默认的描述中寻找
     *
     * @param retCode
     */
    public int setResult(int retCode) {
        return setResult(retCode, null, false);
    }

    public void addResults(Map<String, Object> results) {
        if (results == null) {
            return;
        }
        this.results.putAll(results);
    }

    public int getResultCode() {
        return resultCode;
    }

    public Map<String, Object> getResults() {
        return results;
    }


    public String getResult() {
        return result;
    }

    /**
     * 字符串结果，如果设置了，将不处理map结果
     *
     * @param result
     */
    public void setResult(String result) {
        this.result = result;
    }

    public HttpServletResponse getResponse() {
        return response;
    }

    public void setResponse(HttpServletResponse response) {
        this.response = response;
    }

}
